/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * ieee80211_header.c
 * Copyright (C) chemek anouar 2012 <anouar.chemek@esprit.tn>
 *
 * WiScramb is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * WiScramb is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef _IEEE82011_HEADER_H
#define _IEEE82011_HEADER_H
#include <stdint.h>

#define	IEEE80211_ADDR_LEN	6		/* size of 802.11 address */
/* The radio capture header precedes the 802.11 header. */
#define BUF_SIZE 2352

#define FCS_LEN 4



#define IEEE80211_FTYPE_MGMT            0
#define IEEE80211_FTYPE_CTL             1
#define IEEE80211_FTYPE_DATA            2

/* management */
#define IEEE80211_STYPE_ASSOC_REQ       0x0
#define IEEE80211_STYPE_ASSOC_RESP      0x1
#define IEEE80211_STYPE_REASSOC_REQ     0x2
#define IEEE80211_STYPE_REASSOC_RESP    0x3
#define IEEE80211_STYPE_PROBE_REQ       0x4
#define IEEE80211_STYPE_PROBE_RESP      0x5
#define IEEE80211_STYPE_BEACON          0x8
#define IEEE80211_STYPE_ATIM            0x9
#define IEEE80211_STYPE_DISASSOC        0xA
#define IEEE80211_STYPE_AUTH            0xB
#define IEEE80211_STYPE_DEAUTH          0xC
#define IEEE80211_STYPE_ACTION          0xD
#define IEEE80211_STYPE_TIMING_ADVERTISSEMENT   0x7
#define IEEE80211_STYPE_SBEACON         0xE

/* control */
#define IEEE80211_STYPE_BACK_REQ        0x8
#define IEEE80211_STYPE_BACK            0x9
#define IEEE80211_STYPE_PSPOLL          0xA
#define IEEE80211_STYPE_RTS             0xB
#define IEEE80211_STYPE_CTS             0xC
#define IEEE80211_STYPE_ACK             0xD
#define IEEE80211_STYPE_CFEND           0xE
#define IEEE80211_STYPE_CFENDACK        0xF

/* data */
#define IEEE80211_STYPE_DATA                    0x0
#define IEEE80211_STYPE_DATA_CFACK              0x1
#define IEEE80211_STYPE_DATA_CFPOLL             0x2
#define IEEE80211_STYPE_DATA_CFACKPOLL          0x3
#define IEEE80211_STYPE_NULLFUNC                0x4
#define IEEE80211_STYPE_CFACK                   0x5
#define IEEE80211_STYPE_CFPOLL                  0x6
#define IEEE80211_STYPE_CFACKPOLL               0x7
#define IEEE80211_STYPE_QOS_DATA                0x8
#define IEEE80211_STYPE_QOS_DATA_CFACK          0x9
#define IEEE80211_STYPE_QOS_DATA_CFPOLL         0xA
#define IEEE80211_STYPE_QOS_DATA_CFACKPOLL      0xB
#define IEEE80211_STYPE_QOS_NULLFUNC            0xC
#define IEEE80211_STYPE_QOS_CFACK               0xD
#define IEEE80211_STYPE_QOS_CFPOLL              0xE
#define IEEE80211_STYPE_QOS_CFACKPOLL           0xF


/* miscellaneous IEEE 802.11 constants */
#define IEEE80211_MAX_FRAG_THRESHOLD    2352
#define IEEE80211_MAX_RTS_THRESHOLD     2353
#define IEEE80211_MAX_AID               2007
#define IEEE80211_MAX_TIM_LEN           251

/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
   6.2.1.1.2.

   802.11e clarifies the figure in section 7.1.2. The frame body is
   up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */
#define IEEE80211_MAX_DATA_LEN          2304
/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
#define IEEE80211_MAX_FRAME_LEN         2352

#define IEEE80211_MAX_SSID_LEN          32


#define WLAN_SA_QUERY_TR_ID_LEN 16

//TODO http://www.radiotap.org/
struct ieee80211_radiotap_header {
  u_int8_t header_revesion;
  u_int8_t header_pad;
  u_int16_t header_lenght;
  u_int32_t present_flags;
  u_int64_t mac_timestamp;
  u_int8_t flags;
  u_int8_t data_rates;
  u_int16_t channel_frequency;
  u_int16_t channel_type;
  u_int8_t ssi_signal;
  u_int8_t antenna;
  u_int16_t rx_flags;
};
typedef struct ieee80211_radiotap_header ieee80211_radiotap_header;
struct frame_control {
  u_int8_t protocol_version: 2;
  u_int8_t type: 2;
  u_int8_t sub_type: 4;
  u_int8_t to_ds: 1;
  u_int8_t from_ds: 1;
  u_int8_t more_frag: 1;
  u_int8_t rety: 1;
  u_int8_t pwr_mgmt: 1;
  u_int8_t more_data: 1;
  u_int8_t web: 1;
  u_int8_t order: 1;
};
typedef struct frame_control frame_control;
/*
 * generic definitions for IEEE 802.11 frames
 */
struct ieee80211_mac_header {
  frame_control fc;
  //u_int16_t frame_ctrl;
  u_int16_t duration;
  u_int8_t addr1[IEEE80211_ADDR_LEN];
  u_int8_t addr2[IEEE80211_ADDR_LEN];
  u_int8_t addr3[IEEE80211_ADDR_LEN];
  /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
  u_int16_t sequence_ctrl;
};
typedef struct ieee80211_mac_header ieee80211_mac_header;



/*struct ieee80211_header {
	ieee80211_radiotap_header radiotap_header;
	ieee80211_mac_header mac_header;
};
typedef struct ieee80211_header ieee80211_header;*/

/**
 * struct ieee80211_channel_sw_ie
 *
 * This structure refers to "Channel Switch Announcement information element"
 */
struct ieee80211_channel_sw_ie {
  u_int8_t mode;
  u_int8_t new_ch_num;
  u_int8_t count;
};
typedef struct ieee80211_channel_sw_ie ieee80211_channel_sw_ie;

/**
 * struct ieee80211_msrment_ie
 *
 * This structure refers to "Measurement Request/Report information element"
 */
struct ieee80211_msrment_ie {
  u_int8_t token;
  u_int8_t mode;
  u_int8_t type;
  u_int8_t request[0];
};
typedef struct ieee80211_msrment_ie ieee80211_msrment_ie;


/* Information Element IDs */
enum ieee80211_eid {
        WLAN_EID_SSID = 0,
        WLAN_EID_SUPP_RATES = 1,
        WLAN_EID_FH_PARAMS = 2,
        WLAN_EID_DS_PARAMS = 3,
        WLAN_EID_CF_PARAMS = 4,
        WLAN_EID_TIM = 5,
        WLAN_EID_IBSS_PARAMS = 6,
        WLAN_EID_CHALLENGE = 16,
        /* 802.11d */
        WLAN_EID_COUNTRY = 7,
        WLAN_EID_HP_PARAMS = 8,
        WLAN_EID_HP_TABLE = 9,
        WLAN_EID_REQUEST = 10,
        /* 802.11e */
        WLAN_EID_QBSS_LOAD = 11,
        WLAN_EID_EDCA_PARAM_SET = 12,
        WLAN_EID_TSPEC = 13,
        WLAN_EID_TCLAS = 14,
        WLAN_EID_SCHEDULE = 15,
        WLAN_EID_TS_DELAY = 43,
        WLAN_EID_TCLAS_PROCESSING = 44,
        WLAN_EID_QOS_CAPA = 46,
        /* 802.11s
         *
         * All mesh EID numbers are pending IEEE 802.11 ANA approval.
         * The numbers have been incremented from those suggested in
         * 802.11s/D2.0 so that MESH_CONFIG does not conflict with
         * EXT_SUPP_RATES.
         */
        WLAN_EID_MESH_CONFIG = 51,
        WLAN_EID_MESH_ID = 52,
        WLAN_EID_PEER_LINK = 55,
        WLAN_EID_PREQ = 68,
        WLAN_EID_PREP = 69,
        WLAN_EID_PERR = 70,
        /* 802.11h */
        WLAN_EID_PWR_CONSTRAINT = 32,
        WLAN_EID_PWR_CAPABILITY = 33,
        WLAN_EID_TPC_REQUEST = 34,
        WLAN_EID_TPC_REPORT = 35,
        WLAN_EID_SUPPORTED_CHANNELS = 36,
        WLAN_EID_CHANNEL_SWITCH = 37,
        WLAN_EID_MEASURE_REQUEST = 38,
        WLAN_EID_MEASURE_REPORT = 39,
        WLAN_EID_QUIET = 40,
        WLAN_EID_IBSS_DFS = 41,
        /* 802.11g */
        WLAN_EID_ERP_INFO = 42,
        WLAN_EID_EXT_SUPP_RATES = 50,
        /* 802.11n */
        WLAN_EID_HT_CAPABILITY = 45,
        WLAN_EID_HT_INFORMATION = 61,
        /* 802.11i */
        WLAN_EID_RSN = 48,
        WLAN_EID_TIMEOUT_INTERVAL = 56,
        WLAN_EID_MMIE = 76 /* 802.11w */,
        WLAN_EID_WPA = 221,
        WLAN_EID_GENERIC = 221,
        WLAN_EID_VENDOR_SPECIFIC = 221,
        WLAN_EID_QOS_PARAMETER = 222
};

/* Parsed Information Elements */
struct ieee802_11_elems {
        u_int8_t *ie_start;
        size_t total_len;

        /* pointers to IEs */
        u_int8_t *ssid;
        u_int8_t *supp_rates;
        u_int8_t *fh_params;
        u_int8_t *ds_params;
        u_int8_t *cf_params;
        u_int8_t *tim;
        u_int8_t *ibss_params;
        u_int8_t *challenge;
        u_int8_t *wpa;
        u_int8_t *rsn;
        u_int8_t *erp_info;
        u_int8_t *ext_supp_rates;
        u_int8_t *wmm_info;
        u_int8_t *wmm_param;
        struct ieee80211_ht_cap *ht_cap_elem;
        struct ieee80211_ht_info *ht_info_elem;
        u_int8_t *mesh_config;
        u_int8_t *mesh_id;
        u_int8_t *peer_link;
        u_int8_t *preq;
        u_int8_t *prep;
        u_int8_t *perr;
        u_int8_t *ch_switch_elem;
        u_int8_t *country_elem;
        u_int8_t *pwr_constr_elem;
        u_int8_t *quiet_elem;         /* first quite element */
        u_int8_t *timeout_int;

        /* length of them, respectively */
        u_int8_t ssid_len;
        u_int8_t supp_rates_len;
        u_int8_t fh_params_len;
        u_int8_t ds_params_len;
        u_int8_t cf_params_len;
        u_int8_t tim_len;
        u_int8_t ibss_params_len;
        u_int8_t challenge_len;
        u_int8_t wpa_len;
        u_int8_t rsn_len;
        u_int8_t erp_info_len;
        u_int8_t ext_supp_rates_len;
        u_int8_t wmm_info_len;
        u_int8_t wmm_param_len;
        u_int8_t mesh_config_len;
        u_int8_t mesh_id_len;
        u_int8_t peer_link_len;
        u_int8_t preq_len;
        u_int8_t prep_len;
        u_int8_t perr_len;
        u_int8_t ch_switch_elem_len;
        u_int8_t country_elem_len;
        u_int8_t pwr_constr_elem_len;
        u_int8_t quiet_elem_len;
        u_int8_t num_of_quiet_elem;   /* can be more the one */
        u_int8_t timeout_int_len;
};
typedef struct ieee802_11_elems ieee802_11_elems;

struct ieee80211_mgmt {
  union {
    struct {
      __le16 auth_alg;
      __le16 auth_transaction;
      __le16 status_code;
      /* possibly followed by Challenge text */
      u_int8_t variable[0];
    } __attribute__ ((packed)) auth;
    struct {
      __le16 reason_code;
    } __attribute__ ((packed)) deauth;
    struct {
      __le16 capab_info;
      __le16 listen_interval;
      /* followed by SSID and Supported rates */
      u_int8_t variable[0];
    } __attribute__ ((packed)) assoc_req;
    struct {
      __le16 capab_info;
      __le16 status_code;
      __le16 aid;
      /* followed by Supported rates */
      u_int8_t variable[0];
    } __attribute__ ((packed)) assoc_resp, reassoc_resp;
    struct {
      __le64 timestamp;
      __le16 capab_info;
      /* followed by Supported rates */
      u_int8_t variable[0];
    } __attribute__ ((packed)) sbeacon;
    struct {
      __le16 capab_info;
      __le16 listen_interval;
      u_int8_t current_ap[6];
      /* followed by SSID and Supported rates */
      u_int8_t variable[0];
    } __attribute__ ((packed)) reassoc_req;
    struct {
      __le16 reason_code;
    } __attribute__ ((packed)) disassoc;
    struct {
      __le64 timestamp;
      __le16 beacon_int;
      __le16 capab_info;
      /* followed by some of SSID, Supported rates,
       * FH Params, DS Params, CF Params, IBSS Params, TIM */
      u_int8_t variable[0];
    } __attribute__ ((packed)) beacon;
    struct {
      /* only variable items: SSID, Supported rates */
      u_int8_t variable[0];
    } __attribute__ ((packed)) probe_req;
    struct {
      __le64 timestamp;
      __le16 beacon_int;
      __le16 capab_info;
      /* followed by some of SSID, Supported rates,
       * FH Params, DS Params, CF Params, IBSS Params */
      u_int8_t variable[0];
    } __attribute__ ((packed)) probe_resp;
    struct {
      __le64 timestamp;
      __le16 capab_info; //fixed parameter
      /* followed by some of  Supported rates,country,EDCA parameters
       * power constraint,timing, ADDED by ITS_LAB*/
      u_int8_t variable[0];
    } __attribute__ ((packed)) timing_advertissement;
    struct {
      u_int8_t category;
      union {
        struct {
          u_int8_t action_code;
          u_int8_t dialog_token;
          u_int8_t status_code;
          u_int8_t variable[0];
        } __attribute__ ((packed)) wme_action;
        struct{
          u_int8_t action_code;
          u_int8_t element_id;
          u_int8_t length;
          struct ieee80211_channel_sw_ie sw_elem;
        } __attribute__((packed)) chan_switch;
        struct{
          u_int8_t action_code;
          u_int8_t dialog_token;
          u_int8_t element_id;
          u_int8_t length;
          struct ieee80211_msrment_ie msr_elem;
        } __attribute__((packed)) measurement;
        struct{
          u_int8_t action_code;
          u_int8_t dialog_token;
          __le16 capab;
          __le16 timeout;
          __le16 start_seq_num;
        } __attribute__((packed)) addba_req;
        struct{
          u_int8_t action_code;
          u_int8_t dialog_token;
          __le16 status;
          __le16 capab;
          __le16 timeout;
        } __attribute__((packed)) addba_resp;
        struct{
          u_int8_t action_code;
          __le16 params;
          __le16 reason_code;
        } __attribute__((packed)) delba;
        struct{
          u_int8_t action_code;
          /* capab_info for open and confirm,
           * reason for close
           */
          __le16 aux;
          /* Followed in plink_confirm by status
           * code, AID and supported rates,
           * and directly by supported rates in
           * plink_open and plink_close
           */
          u_int8_t variable[0];
        } __attribute__((packed)) plink_action;
        struct{
          u_int8_t action_code;
          u_int8_t variable[0];
        } __attribute__((packed)) mesh_action;
        struct {
          u_int8_t action;
          u_int8_t trans_id[WLAN_SA_QUERY_TR_ID_LEN];
        } __attribute__ ((packed)) sa_query;
      } u;
    } __attribute__ ((packed)) action;
  } u;
};

typedef struct ieee80211_mgmt ieee80211_mgmt;
#endif
